 /*
 * Author: ehpalumbo
 * Description: Logging Utilities.
 */

#ifndef LOGGING
#define LOGGING

#include <string>
#include <exception>
#include <map>

using namespace std;

namespace logging {


	enum Level {
		TRACE, DEBUG, INFO, WARN, ERROR, FATAL, OFF
	};


	class Logger {
		public:
			Logger() {};
			virtual void log(Level detailLevel, const string& aMessage) =0;
			virtual void log(Level detailLevel, const char* aMessage) =0;
			virtual void log(Level detailLevel, const string& aMessage, const exception& thrown) =0;
			virtual void log(Level detailLevel, const char* aMessage, const exception& thrown) =0;
			virtual ~Logger() {}
	};


	class LoggerImpl: public Logger {
	protected:
		Level threshold;
		const char* name;
	public:
		LoggerImpl(const char* name, Level threshold);
		void log(Level detailLevel, const string& aMessage);
		void log(Level detailLevel, const char* aMessage);
		void log(Level detailLevel, const string& aMessage, const exception& thrown);
		void log(Level detailLevel, const char* aMessage, const exception& thrown);
		void setThresholdLevel(Level threshold);
		virtual ~LoggerImpl();
	};


	class LoggerFactory {
	private:
		Level applicationLevel;
		map<string, Logger*>* loggers;
		LoggerImpl* rootLogger;
		LoggerFactory();
		~LoggerFactory();
		static LoggerFactory* instance;
	public:
		void setApplicationLevel(Level applicationLevel);
		Logger& getRootLogger();
		Logger& getLogger(const char* loggerName);
		Logger& getLogger(const string& loggerName);
		static LoggerFactory& getInstance();
		static void shutdownLogging();
	};

}


#endif
